package com.tankbattle.stage.body;


import com.tankbattle.enums.DirectionEnum;
import com.tankbattle.enums.EnemyPositionEnum;
import com.tankbattle.enums.PowerEnum;
import com.tankbattle.enums.TankTypeEnum;
import com.tankbattle.stage.body.buildings.*;
import com.tankbattle.stage.body.map.Map;
import com.tankbattle.stage.body.power.*;
import com.tankbattle.stage.body.scores.Score;
import com.tankbattle.stage.body.tank.Enemy;
import com.tankbattle.stage.body.tank.Player;
import com.tankbattle.stage.body.tank.Tank;
import com.tankbattle.utils.GetResource;

import javax.swing.*;
import java.applet.Applet;
import java.applet.AudioClip;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

import static com.tankbattle.enums.DirectionEnum.*;
import static com.tankbattle.enums.PowerEnum.NO_POWER;
import static com.tankbattle.enums.TankTypeEnum.*;


// w: UP a: LEFT s: DOWN d: RIGHT space: SHOOT
// type 0: stand for player's tank
// type 1: stand for enemy's tank
// using Thread.sleep to slow repainting down
/* in tanks Array
   0: stand for nothing
   1:stand for tank..
   2:stand for steel
   3:stand for home
   4:stand for wall
   5:stand for sea.
   6:stand for timer
   7:stand for addLife
   8:stand for boom
   9:stand for shield
   10:stand for stars
*/
public class StageBody extends JPanel implements KeyListener, Runnable, GetResource {

    public static List<Steel> steels;
    public static List<Wall> walls;
    public static Map map;
    public static AudioClip bcgbgm;
    public static AudioClip blastbgm;
    public static Boolean homeAlive = true;
    public static Power power = null;
    ImageIcon bulletUImage = new ImageIcon(getResource("img/bulletU.png"));
    ImageIcon bulletLImage = new ImageIcon(getResource("img/bulletL.png"));
    ImageIcon bulletDImage = new ImageIcon(getResource("img/bulletD.png"));
    ImageIcon bulletRImage = new ImageIcon(getResource("img/bulletR.png"));
    ImageIcon backgroundImage = new ImageIcon(getResource("img/body.png"));
    ImageIcon wallImage = new ImageIcon(getResource("img/wall.png"));
    ImageIcon seaImage = new ImageIcon(getResource("img/sea.gif"));
    ImageIcon homeImage = new ImageIcon(getResource("img/home.png"));
    ImageIcon iceImage = new ImageIcon(getResource("img/ice.png"));
    ImageIcon destroyImage = new ImageIcon(getResource("img/destroy.png"));
    ImageIcon grassImage = new ImageIcon(getResource("img/grass.png"));
    ImageIcon gameOverImage = new ImageIcon(getResource("img/over.png"));
    ImageIcon steelToWall = new ImageIcon(getResource("img/steelWall.gif"));
    ImageIcon steelImage = new ImageIcon(getResource("img/steel2.png"));
    ImageIcon upImage = new ImageIcon(getResource("img/p1tankU.png"));
    ImageIcon leftImage = new ImageIcon(getResource("img/p1tankL.png"));
    ImageIcon downImage = new ImageIcon(getResource("img/p1tankD.png"));
    ImageIcon rightImage = new ImageIcon(getResource("img/p1tankR.png"));
    ImageIcon up2Image = new ImageIcon(getResource("img/p1tankU2.png"));
    ImageIcon left2Image = new ImageIcon(getResource("img/p1tankL2.png"));
    ImageIcon down2Image = new ImageIcon(getResource("img/p1tankD2.png"));
    ImageIcon right2Image = new ImageIcon(getResource("img/p1tankR2.png"));
    ImageIcon upMoveImage = new ImageIcon(getResource("img/p1Umove.gif"));
    ImageIcon downMoveImage = new ImageIcon(getResource("img/p1Dmove.gif"));
    ImageIcon leftMoveImage = new ImageIcon(getResource("img/p1Lmove.gif"));
    ImageIcon rightMoveImage = new ImageIcon(getResource("img/p1Rmove.gif"));
    ImageIcon enemyDImage = new ImageIcon(getResource("img/enemyD.png"));
    ImageIcon enemyLImage = new ImageIcon(getResource("img/enemyL.png"));
    ImageIcon enemyUImage = new ImageIcon(getResource("img/enemyU.png"));
    ImageIcon enemyRImage = new ImageIcon(getResource("img/enemyR.png"));
    ImageIcon enemy2UImage = new ImageIcon(getResource("img/enemy2U.gif"));
    ImageIcon enemy2DImage = new ImageIcon(getResource("img/enemy2D.gif"));
    ImageIcon enemy2RImage = new ImageIcon(getResource("img/enemy2R.gif"));
    ImageIcon enemy2LImage = new ImageIcon(getResource("img/enemy2L.gif"));
    ImageIcon enemy3UImage = new ImageIcon(getResource("img/enemy3U.png"));
    ImageIcon enemy3DImage = new ImageIcon(getResource("img/enemy3D.png"));
    ImageIcon enemy3RImage = new ImageIcon(getResource("img/enemy3R.png"));
    ImageIcon enemy3LImage = new ImageIcon(getResource("img/enemy3L.png"));
    ImageIcon enemy3UMoveImage = new ImageIcon(getResource("img/enemy3Umove.gif"));
    ImageIcon enemy3DMoveImage = new ImageIcon(getResource("img/enemy3Dmove.gif"));
    ImageIcon enemy3RMoveImage = new ImageIcon(getResource("img/enemy3Rmove.gif"));
    ImageIcon enemy3LMoveImage = new ImageIcon(getResource("img/enemy3Lmove.gif"));
    ImageIcon enemyLmoveImage = new ImageIcon(getResource("img/enemyLmove.gif"));
    ImageIcon enemyRmoveImage = new ImageIcon(getResource("img/enemyRmove.gif"));
    ImageIcon enemyDmoveImage = new ImageIcon(getResource("img/enemyDmove.gif"));
    ImageIcon enemyUmoveImage = new ImageIcon(getResource("img/enemyUmove.gif"));
    ImageIcon blast1Image = new ImageIcon(getResource("img/blast1.png"));
    ImageIcon blast2Image = new ImageIcon(getResource("img/blast2.png"));
    ImageIcon blast3Image = new ImageIcon(getResource("img/blast3.png"));
    ImageIcon blast4Image = new ImageIcon(getResource("img/blast4.png"));
    ImageIcon blast5Image = new ImageIcon(getResource("img/blast5.png"));
    ImageIcon blast6Image = new ImageIcon(getResource("img/blast6.png"));
    ImageIcon blast7Image = new ImageIcon(getResource("img/blast7.png"));
    // tools: 加盾、加生命条、时间暂停、自爆
    ImageIcon shieldImage = new ImageIcon(getResource("img/shield.gif"));
    ImageIcon boomImage = new ImageIcon(getResource("img/boom.gif"));
    ImageIcon addLifeImage = new ImageIcon(getResource("img/addLife.gif"));
    ImageIcon timeImage = new ImageIcon(getResource("img/timer.gif"));
    ImageIcon addShieldImage = new ImageIcon(getResource("img/addShield.gif"));
    ImageIcon addScoreImage = new ImageIcon(getResource("img/addScore.gif"));
    ImageIcon steelHomeImage = new ImageIcon(getResource("img/steelHome.gif"));
    ImageIcon born1Image = new ImageIcon(getResource("img/born1.png"));
    ImageIcon born2Image = new ImageIcon(getResource("img/born2.png"));
    ImageIcon born3Image = new ImageIcon(getResource("img/born3.png"));
    ImageIcon born4Image = new ImageIcon(getResource("img/born4.png"));
    ImageIcon fastUImage = new ImageIcon(getResource("img/enemyFU.gif"));
    ImageIcon fastLImage = new ImageIcon(getResource("img/enemyFL.gif"));
    ImageIcon fastDImage = new ImageIcon(getResource("img/enemyFD.gif"));
    ImageIcon fastRImage = new ImageIcon(getResource("img/enemyFR.gif"));
    Player playerTank;
    /**
     * 奖励数
     */
    int enemyTanksAward = 0;
    int enemyTanksNumber = 4;
    /**
     * 敌方坦克数量
     */
    int enemyTanksNumberLimit = 1;
    int enemyTanksFatty = 0;
    List<Boom> bulletBoom = new ArrayList<>();
    CopyOnWriteArrayList<Enemy> enemyTanks;
    List<Sea> seas;
    List<Grass> grasses;
    List<Ice> ices;
    Score score;
    GameOver gameOver = null;
    Boolean win = false;
    Boolean once = true;
    Boolean once1 = true;
    Boolean delay = false;
    Boolean enemyMove = true;
    long shieldTime = 5000;
    // 做无敌时间计时
    long clock = 0;
    // 做停止移动的计时
    long clock2 = 0;
    // 做铁制房子的倒计时
    long clock3 = 0;
    // 做道具的倒计时
    long clock4 = 0;
    Boolean up = false;
    Boolean left = false;
    Boolean down = false;
    Boolean right = false;
    Boolean stop = true;

    @SuppressWarnings("unchecked")
    public StageBody() {

        this.seas = map.getSeas();
        this.grasses = map.getGrasses();
        this.steels = map.getSteels();
        this.walls = map.getWalls();
        this.ices = map.getIces();

        //积分系统
        score = new Score();
        // init player tank
        this.playerTank = new Player(260 - 32 - 32 - 16, 520 - 32);
        this.enemyTanks = new CopyOnWriteArrayList<Enemy>();
        // init enemy tanks
        for (int numbers = 0; numbers < enemyTanksNumber; numbers++) {
            Enemy enemy = new Enemy((numbers + 1) * 110, 0);
            enemy.setType(ORDINARY_ENEMY);
            enemy.setMoving(false);
            enemy.setDirection(DOWN);
            this.enemyTanks.add(enemy);
            new Thread(enemy).start();
        }
        // 加载音乐文件, 防止反复的加载而卡顿
        bcgbgm = Applet.newAudioClip(getResource("bgm/move.wav"));
        blastbgm = Applet.newAudioClip(getResource("bgm/blast.wav"));
    }

    @Override
    public void paintComponent(Graphics g) {

        try {
            Thread.sleep(20);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        g.drawImage(backgroundImage.getImage(), 0, 0, this);

        // paint power
        if (power != null) {
            if (power.getAlive()) {
                if (clock4 == 0) {
                    clock4 = System.currentTimeMillis();
                } else {
                    if (System.currentTimeMillis() - clock4 >= 12000) {
                        power.setAlive(false);
                        power.setType(null);
                        clock4 = 0;
                    }
                }
                switch (power.getType()) {
                    case CLOCK:
                        g.drawImage(timeImage.getImage(), power.getX(), power.getY(), this);
                        break;
                    case LIFE:
                        g.drawImage(addLifeImage.getImage(), power.getX(), power.getY(), this);
                        break;
                    case BOOM:
                        g.drawImage(boomImage.getImage(), power.getX(), power.getY(), this);
                        break;
                    case SHIELD:
                        g.drawImage(addShieldImage.getImage(), power.getX(), power.getY(), this);
                        break;
                    case STAR:
                        g.drawImage(addScoreImage.getImage(), power.getX(), power.getY(), this);
                        break;
                    case STEEL_HOME:
                        g.drawImage(steelHomeImage.getImage(), power.getX(), power.getY(), this);
                        break;
                    default:
                        power = null;
                        break;
                }
                // then enemys stop moving
            } else {
                if (power.getType() != null) {
                    switch (power.getType()) {
                        case CLOCK:
                            enemyTanksStopMove();
                            if (clock2 == 0) {
                                this.enemyMove = false;
                                clock2 = System.currentTimeMillis();
                                bcgbgm.stop();
                            } else {
                                if (System.currentTimeMillis() - clock2 >= 12000) {
                                    bcgbgm.loop();
                                    enemyTanksMove();
                                    this.enemyMove = true;
                                    power = null;
                                    clock2 = 0;
                                    // 计算吃到道具的个数
                                    score.setTool(score.getTool() + 1);
                                }
                            }
                            break;
                        case LIFE:
                            this.playerTank.setLife(this.playerTank.getLife() + 1);
                            // 计算吃到道具的个数
                            score.setTool(score.getTool() + 1);
                            power = null;
                            break;
                        case BOOM:
                            enemyTanksAllDie();
                            // 计算吃到道具的个数
                            score.setTool(score.getTool() + 1);
                            power = null;
                            break;
                        case SHIELD:
                            this.playerTank.setBeatable(false);
                            // 计算吃到道具的个数
                            score.setTool(score.getTool() + 1);
                            power = null;
                            break;
                        case STAR:
                            // 双倍得分
                            // 计算吃到道具的个数
                            score.setTool(score.getTool() + 1);
                            this.playerTank.setFastBullet(true);
                            power = null;
                            break;
                        case STEEL_HOME:
                            // 铁房子
                            if (once1) {
                                steelHome();
                                once1 = false;
                            }
                            if (clock3 == 0) {
                                clock3 = System.currentTimeMillis();
                            } else {
                                if (System.currentTimeMillis() - clock3 >= 20000) {
                                    // 重变回砖头
                                    steelToWallHome();
                                    power = null;
                                    score.setTool(score.getTool() + 1);
                                    clock3 = 0;
                                }
                            }
                            break;
                        default:
                            break;
                    }

                }
            }
        }

        // paint ices
        for (Ice ice : this.ices) {
            g.drawImage(iceImage.getImage(), ice.getX(), ice.getY(), this);
        }

        // draw player's tank 5.0
        long ext = this.playerTank.getExtTime();
        if (!this.playerTank.isVisible() && (System.currentTimeMillis() - ext >= 10)) {
            this.playerTank.setExtTime(System.currentTimeMillis());
            this.playerTank.setMoving(false);
            this.stop = true;
            if (this.playerTank.getWhenBornPaintTimes() > 3) {
                g.drawImage(born1Image.getImage(), this.playerTank.getX(), this.playerTank.getY(), this);
            } else if (this.playerTank.getWhenBornPaintTimes() > 2) {
                g.drawImage(born2Image.getImage(), this.playerTank.getX(), this.playerTank.getY(), this);
            } else if (this.playerTank.getWhenBornPaintTimes() > 1) {
                g.drawImage(born3Image.getImage(), this.playerTank.getX(), this.playerTank.getY(), this);
            } else if (this.playerTank.getWhenBornPaintTimes() > 0) {
                g.drawImage(born4Image.getImage(), this.playerTank.getX(), this.playerTank.getY(), this);
                this.playerTank.setMoving(true);
                this.playerTank.setVisible(true);
            } else {
                this.playerTank.setVisible(true);
            }
            this.playerTank.cut();
        } else if (playerTank.isAlive()) {

            paintTank(g, PLAYER, this.playerTank.getX(), this.playerTank.getY(), this.playerTank.getDirection());

            if (!this.playerTank.getBeatable()) {
                if (clock == 0) {
                    clock = System.currentTimeMillis();
                }
                if (System.currentTimeMillis() - clock >= shieldTime) {
                    this.playerTank.setBeatable(true);
                    clock = 0;
                }
            }
            if (!this.playerTank.getBeatable()) {
                // new born
                g.drawImage(shieldImage.getImage(), this.playerTank.getX(), this.playerTank.getY(), this);
            }
            this.playerTank.move(this.stop);

        } else {
            // if life > 0 then resurgence place 这里需要延迟一下,防止刚复活奇怪的事情发生
            if (playerTank.getLife() == 0) {
                // game is over the gif is like a bullet
                if (this.gameOver == null) {
                    this.gameOver = new GameOver(260 - 40, 520);
                    new Thread(this.gameOver).start();
                    playerTank.setLife(-1);
                }

            } else {
                this.playerTank.setX(260 - 32 - 32 - 16);
                this.playerTank.setY(520 - 32);
            }
        }

        // paint walls
        for (Wall wall : walls) {
            if (wall.getAlive()) {
                g.drawImage(wallImage.getImage(), wall.getX(), wall.getY(), this);
            }
        }

        // paint sea
        for (Sea sea : this.seas) {
            g.drawImage(seaImage.getImage(), sea.getX(), sea.getY(), this);
        }

        // draw player's bullets
        CopyOnWriteArrayList<Bullet> bullets = this.playerTank.getBulletPool();
        for (Bullet bullet : bullets) {
            if (bullet != null) {
                if (bullet.isAlive()) {
                    switch (bullet.getDirection()) {
                        case DOWN:
                            g.drawImage(bulletUImage.getImage(), bullet.getX(), bullet.getY(), this);
                            break;
                        case LEFT:
                            g.drawImage(bulletLImage.getImage(), bullet.getX(), bullet.getY(), this);
                            break;
                        case UP:
                            g.drawImage(bulletDImage.getImage(), bullet.getX(), bullet.getY(), this);
                            break;
                        case RIGHT:
                            g.drawImage(bulletRImage.getImage(), bullet.getX(), bullet.getY(), this);
                            break;
                        default:
                            break;
                    }
                } else if (bullet.isHitBuilding()) {
                    if (bullet.getBoomPlace() != null) {
                        this.bulletBoom.add(new Boom(bullet.getBoomPlace().getX(), bullet.getBoomPlace().getY()));
                    } else {
                        this.bulletBoom.add(new Boom(bullet.getX(), bullet.getY()));
                    }
                    bullet.setHitBuilding(false);
                    if (bullet.getHitSteel()) {
                        AudioClip bgm = Applet.newAudioClip(getResource("bgm/hitLimit.wav"));
                        bgm.play();
                    }
                }
            }
        }

        // draw enemy tanks and born.gif
        int aliveTanks = 0;
        for (Enemy temp : this.enemyTanks) {
            long exts = temp.getExtTime();
            if (!temp.isVisible() && (System.currentTimeMillis() - exts >= 80)) {
                temp.setExtTime(System.currentTimeMillis());
                if (temp.getWhenBornPaintTimes() > 3) {
                    g.drawImage(born1Image.getImage(), temp.getX(), temp.getY(), this);
                } else if (temp.getWhenBornPaintTimes() > 2) {
                    g.drawImage(born2Image.getImage(), temp.getX(), temp.getY(), this);
                } else if (temp.getWhenBornPaintTimes() > 1) {
                    g.drawImage(born3Image.getImage(), temp.getX(), temp.getY(), this);
                } else if (temp.getWhenBornPaintTimes() > 0) {
                    g.drawImage(born4Image.getImage(), temp.getX(), temp.getY(), this);
                    temp.setMoving(true);
                    temp.setVisible(true);
                } else {

                }
                temp.cut();
                aliveTanks += 1;
                continue;
            }
            if (temp.isAlive()) {
                aliveTanks += 1;
                if (temp.isVisible()) {
                    //血厚的扣血
                    if (temp.getType() == FATTY_ENEMY) {
                        if (temp.getLife() == 2) {
                            paintTank(g, temp.getType(), temp.getX(), temp.getY(), temp.getDirection());
                        } else if (temp.getLife() == 1) {
                            temp.setType(FATTY_MINI_ENEMY);
                            paintTank(g, temp.getType(), temp.getX(), temp.getY(), temp.getDirection());
                        }
                    } else {
                        paintTank(g, temp.getType(), temp.getX(), temp.getY(), temp.getDirection());
                    }
                }
            }

            // paint enemy bullet
            Iterator<Bullet> t = temp.getBulletPool().iterator();
            while (t.hasNext()) {
                try {
                    Bullet bullet = t.next();
                    if (bullet.isHitBuilding()) {
                        if (bullet.getBoomPlace() != null) {
                            this.bulletBoom.add(new Boom(bullet.getBoomPlace().getX(), bullet.getBoomPlace().getY()));
                        } else {
                            this.bulletBoom.add(new Boom(bullet.getX(), bullet.getY()));
                        }
                        bullet.setHitBuilding(false);
                    } else if (bullet.isAlive()) {
                        switch (bullet.getDirection()) {
                            case DOWN:
                                g.drawImage(bulletUImage.getImage(), bullet.getX(), bullet.getY(), this);
                                break;
                            case LEFT:
                                g.drawImage(bulletLImage.getImage(), bullet.getX(), bullet.getY(), this);
                                break;
                            case UP:
                                g.drawImage(bulletDImage.getImage(), bullet.getX(), bullet.getY(), this);
                                break;
                            case RIGHT:
                                g.drawImage(bulletRImage.getImage(), bullet.getX(), bullet.getY(), this);
                                break;
                            default:
                                break;
                        }

                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

        }

        // 补充死亡的坦克
        if ((aliveTanks < enemyTanksNumber) && (enemyTanksNumberLimit > 0)) {
            for (int from = 0; from < enemyTanksNumber - aliveTanks; from++) {
                if (enemyTanksNumberLimit <= 0) {
                    break;
                } else {
                    Enemy enemy = null;
                    switch (EnemyPositionEnum.randomPosition()) {
                        case LEFT:
                            enemy = new Enemy(10, 0);
                            break;
                        case CENTRE:
                            enemy = new Enemy(270, 0);
                            break;
                        case RIGHT:
                            enemy = new Enemy(480, 0);
                            break;
                    }
                    enemy.setType(TankTypeEnum.randomEnemyTank());
                    //不能直接生成血厚的残血版本；
                    if (enemy.getType() == FATTY_MINI_ENEMY) {
                        if (enemyTanksAward <= 0) {
                            enemy.setType(ORDINARY_ENEMY);
                        } else {
                            enemy.setType(QUICK_ENEMY);
                            enemy.setAward(PowerEnum.randomPower());
                            enemy.setSpeed(16);
                            enemyTanksAward--;
                        }
                    }

                    if (enemy.getType() == FATTY_ENEMY) {
                        if (this.enemyTanksFatty <= 0) {
                            enemy.setType(QUICK_ENEMY);
                        } else {
                            enemy.setLife(2);
                            this.enemyTanksFatty--;
                        }
                    }
                    enemy.setMoving(false);
                    enemy.setDirection(DOWN);
                    this.enemyTanks.add(enemy);
                    new Thread(enemy).start();
                    this.enemyTanksNumberLimit -= 1;
                    aliveTanks += 1;
                }
            }
        }
        if (aliveTanks == 0) {
            enemyTanksNumberLimit = -1;
            bcgbgm.stop();
        }

        // draw buldings such as grass, heal
        // paint steel
        for (Steel steel : steels) {
            g.drawImage(steelImage.getImage(), steel.getX(), steel.getY(), this);
        }

        // draw boom
        for (int from = 0; from < this.bulletBoom.size(); from++) {
            Boom boom = (Boom) (this.bulletBoom.get(from));
            if (boom.isAlive()) {
                if (boom.drawTimes > 6) {
                    g.drawImage(blast1Image.getImage(), boom.getLx(), boom.getLy(), this);
                    if (boom.isPlay()) {
                        blastbgm.play();
                    }
                } else if (boom.drawTimes > 5) {
                    g.drawImage(blast2Image.getImage(), boom.getLx(), boom.getLy(), this);
                } else if (boom.drawTimes > 4) {
                    g.drawImage(blast3Image.getImage(), boom.getLx(), boom.getLy(), this);
                } else if (boom.drawTimes > 3) {
                    g.drawImage(blast4Image.getImage(), boom.getLx(), boom.getLy(), this);
                } else if (boom.drawTimes > 2) {
                    g.drawImage(blast5Image.getImage(), boom.getLx(), boom.getLy(), this);
                } else if (boom.drawTimes > 1) {
                    g.drawImage(blast6Image.getImage(), boom.getLx(), boom.getLy(), this);
                } else if (boom.drawTimes > 0) {
                    g.drawImage(blast7Image.getImage(), boom.getLx(), boom.getLy(), this);
                }
                boom.cut();
            } else {
                this.bulletBoom.remove(boom);
            }
        }

        // grass
        for (Grass grass : this.grasses) {
            g.drawImage(grassImage.getImage(), grass.getX(), ((Grass) grass).getY(), this);
        }

        // draw home.gif
        if (homeAlive) {
            g.drawImage(homeImage.getImage(), 244, 488, this);
        } else {
            g.drawImage(destroyImage.getImage(), 244, 488, this);
            playerTank.setMoving(false);
            stop = true;
            if (once) {
                if (this.gameOver == null) {
                    this.gameOver = new GameOver(220, 520);
                    new Thread(this.gameOver).start();
                    once = false;
                }
            }
        }

        if (this.gameOver != null) {
            g.drawImage(gameOverImage.getImage(), this.gameOver.getX(), this.gameOver.getY(), 80, 45, this);
            bcgbgm.stop();
        }

    }

    // in tanks array initialize walls location
    public void initWallLocation() {
        for (Wall wall : walls) {
            for (int i = 0; i < 32; i++) {
                for (int j = 0; j < 32; j++) {
                    Tank.tanks[wall.getX() + i][wall.getY() + j] = 4;
                }
            }
        }
    }

    // in tanks array initialize steel location
    public void initSteelLocation() {
        for (Steel steel : steels) {
            for (int i = 0; i < 32; i++) {
                for (int j = 0; j < 32; j++) {
                    Tank.tanks[steel.getX() + i][steel.getY() + j] = 2;
                }
            }
        }
    }

    // whether enemy's tank hit the player's tank
    @SuppressWarnings("unchecked")
    public void ohMyGod() {
        for (Enemy temp : enemyTanks) {
            CopyOnWriteArrayList<Bullet> bulletPool = temp.getBulletPool();
            for (Bullet bullet : bulletPool) {
                if (bullet.isAlive()) {
                    int before = this.playerTank.getLife();
                    scoreAHit(bullet, this.playerTank);
                    if (this.playerTank.getLife() > 0 && this.playerTank.getLife() < before) {
                        this.playerTank.setFastBullet(false);
                        this.playerTank.setDirection(UP);
                        this.playerTank.setAlive(true);
                        this.playerTank.setExtTime(System.currentTimeMillis());
                        this.playerTank.setMoving(false);
                        this.playerTank.setVisible(false);
                        this.playerTank.setWhenBornPaintTimes(4);
                        for (int i = 0; i < 32; i++) {
                            for (int j = 0; j < 32; j++) {
                                if (Tank.tanks[this.playerTank.getX() + i][this.playerTank.getY() + j] == 1) {
                                    Tank.tanks[this.playerTank.getX() + i][this.playerTank.getY() + j] = 0;
                                }
                            }
                        }
                        Boom tankBoom = new Boom(this.playerTank.getX(), this.playerTank.getY());
                        tankBoom.setPlay(true);
                        this.bulletBoom.add(tankBoom);
                        this.delay = true;
                        this.playerTank.setX(260 - 32 - 32 - 16, 1);
                        this.playerTank.setY(520 - 32, 1);
                        this.stop = true;
                        this.playerTank.setBeatable(false);
                        this.left = false;
                        this.right = false;
                        this.up = false;
                        this.down = false;
                        clock = System.currentTimeMillis();
                    }
                }
            }
        }
    }

    // become steel home
    @SuppressWarnings({"static-access", "unchecked"})
    public void steelHome() {
        this.walls.get(0).setAlive(false);
        this.walls.get(1).setAlive(false);
        this.walls.get(2).setAlive(false);
        this.walls.get(3).setAlive(false);
        this.walls.get(4).setAlive(false);
        this.steels.add(new Steel(260 - 16 - 32, 520 - 32));
        this.steels.add(new Steel(260 - 16 - 32, 520 - 32 * 2));
        this.steels.add(new Steel(260 - 16, 520 - 32 * 2));
        this.steels.add(new Steel(260 + 16, 520 - 32));
        this.steels.add(new Steel(260 + 16, 520 - 32 * 2));
        initSteelLocation();
    }

    // steel home to wall home
    @SuppressWarnings({"static-access"})
    public void steelToWallHome() {
        this.walls.get(0).setAlive(true);
        this.walls.get(1).setAlive(true);
        this.walls.get(2).setAlive(true);
        this.walls.get(3).setAlive(true);
        this.walls.get(4).setAlive(true);

        this.steels.remove(new Steel(260 - 16 - 32, 520 - 32));
        this.steels.remove(new Steel(260 - 16 - 32, 520 - 32 * 2));
        this.steels.remove(new Steel(260 - 16, 520 - 32 * 2));
        this.steels.remove(new Steel(260 + 16, 520 - 32));
        this.steels.remove(new Steel(260 + 16, 520 - 32 * 2));

    }

    //
    // enemy tanks can't move
    public void enemyTanksStopMove() {
        for (Enemy enemy : this.enemyTanks) {
            if (enemy.isAlive()) {
                enemy.setMoving(false);
            }
        }
    }

    // enemy tanks in the screen all go die
    public void enemyTanksAllDie() {
        for (Enemy enemy : this.enemyTanks) {
            if (enemy.isAlive()) {
                enemy.setAlive(false);
                Boom boom = new Boom(enemy.getX(), enemy.getY());
                this.bulletBoom.add(boom);
                switch (enemy.getType()) {
                    case ORDINARY_ENEMY:
                        score.setNormalTank(score.getNormalTank() + 1);
                        break;
                    case FATTY_ENEMY:
                        score.setFattyTank(score.getFattyTank() + 1);
                        break;
                    case FATTY_MINI_ENEMY:
                        score.setFattyTank(score.getFattyTank() + 1);
                        break;
                    case QUICK_ENEMY:
                        score.setFastTank(score.getFastTank() + 1);
                        break;
                    default:
                        break;
                }
            }
        }
        AudioClip bgm = Applet.newAudioClip(getResource("bgm/boom.wav"));
        bgm.play();
    }

    // enemy tanks can't move
    public void enemyTanksMove() {
        for (Enemy enemy : this.enemyTanks) {
            if (enemy.isAlive()) {
                enemy.setMoving(true);
            }
        }
    }

    // whether the bullet hit badTank 5.0
    @SuppressWarnings("unchecked")
    public void scoreAHit(Bullet bullet, Tank badTank) {
        if (badTank.getLife() <= 0) {
            // if tank is not survival then return
            return;
        }

        Boom tankBoom = null;
        switch (badTank.getDirection()) {
            case UP:
                if (bullet.getX() >= badTank.getX() && bullet.getX() <= badTank.getX() + 31
                        && bullet.getY() >= badTank.getY() && bullet.getY() <= badTank.getY() + 31) {
                    bullet.setAlive(false);
                    if (badTank.getFlag() == 0) {
                        if (!this.playerTank.getBeatable()) {
                            return;
                        }
                    }
                    badTank.setLife(badTank.getLife() - 1);
                    if (badTank.getLife() <= 0) {
                        badTank.setAlive(false);
                        tankBoom = new Boom(badTank.getX(), badTank.getY());
                        tankBoom.setPlay(true);
                        this.bulletBoom.add(tankBoom);
                    }
                } else if (bullet.getX() + 7 >= badTank.getX() && bullet.getX() + 7 <= badTank.getX() + 31
                        && bullet.getY() >= badTank.getY() && bullet.getY() <= badTank.getY() + 31) {
                    bullet.setAlive(false);
                    if (badTank.getFlag() == 0) {
                        if (!this.playerTank.getBeatable()) {
                            return;
                        }
                    }
                    badTank.setLife(badTank.getLife() - 1);
                    if (badTank.getLife() <= 0) {
                        badTank.setAlive(false);
                        tankBoom = new Boom(badTank.getX(), badTank.getY());
                        tankBoom.setPlay(true);
                        this.bulletBoom.add(tankBoom);
                    }
                }
                break;
            case LEFT:
                // Tank go die
                if (bullet.getX() >= badTank.getX() && bullet.getX() <= badTank.getX() + 31
                        && bullet.getY() + 7 >= badTank.getY() && bullet.getY() + 7 <= badTank.getY() + 31) {
                    bullet.setAlive(false);
                    if (badTank.getFlag() == 0) {
                        if (!this.playerTank.getBeatable()) {
                            return;
                        }
                    }
                    badTank.setLife(badTank.getLife() - 1);
                    if (badTank.getLife() <= 0) {
                        // then play boom gif.
                        badTank.setAlive(false);
                        tankBoom = new Boom(badTank.getX(), badTank.getY());
                        tankBoom.setPlay(true);
                        this.bulletBoom.add(tankBoom);
                    }
                } else if (bullet.getX() + 7 >= badTank.getX() && bullet.getX() + 7 <= badTank.getX() + 31
                        && bullet.getY() + 7 >= badTank.getY() && bullet.getY() + 7 <= badTank.getY() + 31) {
                    bullet.setAlive(false);
                    if (badTank.getFlag() == 0) {
                        if (!this.playerTank.getBeatable()) {
                            return;
                        }
                    }
                    badTank.setLife(badTank.getLife() - 1);
                    if (badTank.getLife() <= 0) {
                        // then play boom gif.
                        badTank.setAlive(false);
                        tankBoom = new Boom(badTank.getX(), badTank.getY());
                        tankBoom.setPlay(true);
                        this.bulletBoom.add(tankBoom);
                    }
                }
                break;
            case DOWN:
                if (bullet.getX() >= badTank.getX() && bullet.getX() <= badTank.getX() + 31
                        && bullet.getY() >= badTank.getY() && bullet.getY() <= badTank.getY() + 31) {
                    bullet.setAlive(false);
                    if (badTank.getFlag() == 0) {
                        if (!this.playerTank.getBeatable()) {
                            return;
                        }
                    }
                    badTank.setLife(badTank.getLife() - 1);
                    if (badTank.getLife() <= 0) {
                        badTank.setAlive(false);
                        tankBoom = new Boom(badTank.getX(), badTank.getY());
                        tankBoom.setPlay(true);
                        this.bulletBoom.add(tankBoom);
                    }
                } else if (bullet.getX() >= badTank.getX() && bullet.getX() <= badTank.getX() + 31
                        && bullet.getY() + 7 >= badTank.getY() && bullet.getY() + 7 <= badTank.getY() + 31) {
                    bullet.setAlive(false);
                    if (badTank.getFlag() == 0) {
                        if (!this.playerTank.getBeatable()) {
                            return;
                        }
                    }
                    badTank.setLife(badTank.getLife() - 1);
                    if (badTank.getLife() <= 0) {
                        badTank.setAlive(false);
                        tankBoom = new Boom(badTank.getX(), badTank.getY());
                        tankBoom.setPlay(true);
                        this.bulletBoom.add(tankBoom);
                    }
                }
                break;
            case RIGHT:
                if (bullet.getX() + 7 >= badTank.getX() && bullet.getX() + 7 <= badTank.getX() + 31
                        && bullet.getY() >= badTank.getY() && bullet.getY() <= badTank.getY() + 31) {
                    bullet.setAlive(false);
                    if (badTank.getFlag() == 0) {
                        if (!this.playerTank.getBeatable()) {
                            return;
                        }
                    }
                    badTank.setLife(badTank.getLife() - 1);
                    if (badTank.getLife() <= 0) {
                        badTank.setAlive(false);
                        tankBoom = new Boom(badTank.getX(), badTank.getY());
                        tankBoom.setPlay(true);
                        this.bulletBoom.add(tankBoom);
                    }
                } else if (bullet.getX() + 7 >= badTank.getX() && bullet.getX() + 7 <= badTank.getX() + 31
                        && bullet.getY() + 7 >= badTank.getY() && bullet.getY() + 7 <= badTank.getY() + 31) {
                    bullet.setAlive(false);
                    if (badTank.getFlag() == 0) {
                        if (!this.playerTank.getBeatable()) {
                            return;
                        }
                    }
                    badTank.setLife(badTank.getLife() - 1);
                    if (badTank.getLife() <= 0) {
                        badTank.setAlive(false);
                        tankBoom = new Boom(badTank.getX(), badTank.getY());
                        tankBoom.setPlay(true);
                        this.bulletBoom.add(tankBoom);
                    }
                }
                break;
            default:
                break;
        }
    }

    // paint the enemy tanks
    private void paintTank(Graphics g, TankTypeEnum type, int x, int y, DirectionEnum direction) {

        switch (direction) {
            case UP:
                if (type == PLAYER) {
                    if (this.playerTank.getFastBullet()) {
                        g.drawImage(up2Image.getImage(), x, y, this);
                    } else {
                        if (!this.stop) {
                            g.drawImage(upImage.getImage(), x, y, this);
                            g.drawImage(upMoveImage.getImage(), x, y, this);
                        } else {
                            g.drawImage(upImage.getImage(), x, y, this);
                        }
                    }
                } else if (type == ORDINARY_ENEMY) {
                    if (this.enemyMove) {
                        g.drawImage(enemyUmoveImage.getImage(), x, y, this);
                    } else {
                        g.drawImage(enemyUImage.getImage(), x, y, this);
                    }
                } else if (type == FATTY_ENEMY) {
                    g.drawImage(enemy2UImage.getImage(), x, y, this);
                } else if (type == FATTY_MINI_ENEMY) {
                    if (this.enemyMove) {
                        g.drawImage(enemy3UMoveImage.getImage(), x, y, this);
                    } else {
                        g.drawImage(enemy3UImage.getImage(), x, y, this);
                    }
                } else {
                    g.drawImage(fastUImage.getImage(), x, y, this);
                }
                break;
            case LEFT:
                if (type == PLAYER) {
                    if (this.playerTank.getFastBullet()) {
                        g.drawImage(left2Image.getImage(), x, y, this);
                    } else {
                        if (!this.stop) {
                            g.drawImage(leftImage.getImage(), x, y, this);
                            g.drawImage(leftMoveImage.getImage(), x, y, this);
                        } else {
                            g.drawImage(leftImage.getImage(), x, y, this);
                        }
                    }
                } else if (type == ORDINARY_ENEMY) {
                    if (this.enemyMove) {
                        g.drawImage(enemyLmoveImage.getImage(), x, y, this);
                    } else {
                        g.drawImage(enemyLImage.getImage(), x, y, this);
                    }
                } else if (type == FATTY_ENEMY) {
                    g.drawImage(enemy2LImage.getImage(), x, y, this);
                } else if (type == FATTY_MINI_ENEMY) {
                    if (this.enemyMove) {
                        g.drawImage(enemy3LMoveImage.getImage(), x, y, this);
                    } else {
                        g.drawImage(enemy3LImage.getImage(), x, y, this);
                    }
                } else {
                    g.drawImage(fastLImage.getImage(), x, y, this);
                }
                break;

            case DOWN:
                if (type == PLAYER) {
                    if (this.playerTank.getFastBullet()) {
                        g.drawImage(down2Image.getImage(), x, y, this);
                    } else {
                        if (!this.stop) {
                            g.drawImage(downImage.getImage(), x, y, this);
                            g.drawImage(downMoveImage.getImage(), x, y, this);
                        } else {
                            g.drawImage(downImage.getImage(), x, y, this);
                        }
                    }
                } else if (type == ORDINARY_ENEMY) {
                    if (this.enemyMove) {
                        g.drawImage(enemyDmoveImage.getImage(), x, y, this);
                    } else {
                        g.drawImage(enemyDImage.getImage(), x, y, this);
                    }
                } else if (type == FATTY_ENEMY) {
                    g.drawImage(enemy2DImage.getImage(), x, y, this);
                } else if (type == FATTY_MINI_ENEMY) {
                    if (this.enemyMove) {
                        g.drawImage(enemy3DMoveImage.getImage(), x, y, this);
                    } else {
                        g.drawImage(enemy3DImage.getImage(), x, y, this);
                    }
                } else {
                    g.drawImage(fastDImage.getImage(), x, y, this);
                }
                break;
            case RIGHT:
                if (type == PLAYER) {
                    if (this.playerTank.getFastBullet()) {
                        g.drawImage(right2Image.getImage(), x, y, this);
                    } else {
                        if (!this.stop) {
                            g.drawImage(rightImage.getImage(), x, y, this);
                            g.drawImage(rightMoveImage.getImage(), x, y, this);
                        } else {
                            g.drawImage(rightImage.getImage(), x, y, this);
                        }
                    }
                } else if (type == ORDINARY_ENEMY) {
                    if (this.enemyMove) {
                        g.drawImage(enemyRmoveImage.getImage(), x, y, this);
                    } else {
                        g.drawImage(enemyRImage.getImage(), x, y, this);
                    }
                } else if (type == FATTY_ENEMY) {
                    g.drawImage(enemy2RImage.getImage(), x, y, this);
                } else if (type == FATTY_MINI_ENEMY) {
                    if (this.enemyMove) {
                        g.drawImage(enemy3RMoveImage.getImage(), x, y, this);
                    } else {
                        g.drawImage(enemy3RImage.getImage(), x, y, this);
                    }
                } else {
                    g.drawImage(fastRImage.getImage(), x, y, this);
                }
                break;

            default:
                break;
        }
        repaint();
    }

    // check bullet meet
    public void bulletMeet() {

        for (Bullet bullet : playerTank.getBulletPool()) {
            if (bullet.isAlive()) {
                for (Enemy enemyTank : enemyTanks) {
                    CopyOnWriteArrayList<Bullet> bullets2 = enemyTank.getBulletPool();
                    for (Bullet b : bullets2) {
                        if (b.isAlive()) {
                            if (Math.abs(b.getX() - bullet.getX()) <= 6 && Math.abs(b.getY() - bullet.getY()) <= 6) {
                                bullet.setAlive(false);
                                b.setAlive(false);
                            }
                        }
                    }

                }
            }

        }
    }

    @Override
    public void run() {

        do {
            try {
                Thread.sleep(100);
            } catch (Exception e) {
                e.printStackTrace();
            }
            // whether hit something
            for (Bullet bullet : playerTank.getBulletPool()) {
                if (bullet.isAlive()) {
                    for (Enemy badTank : enemyTanks) {
                        if (badTank.isAlive()) {
                            scoreAHit(bullet, badTank);
                            if (!badTank.isAlive()) {
                                if (badTank.getAward() != null && badTank.getAward() != NO_POWER) {
                                    if (power == null) {
                                        switch (badTank.getAward()) {
                                            case CLOCK:
                                                power = new Clock(252 + 32, 10);
                                                break;
                                            case LIFE:
                                                power = new Life(252 + 32, 50);
                                                break;
                                            case BOOM:
                                                power = new com.tankbattle.stage.body.power.Boom(252 + 32, 30);
                                                break;
                                            case SHIELD:
                                                power = new Shield(252 + 32, 20);
                                                break;
                                            case STAR:
                                                power = new Star(252 + 32, 10);
                                                break;
                                            case STEEL_HOME:
                                                power = new SteelHome(232 + 32, 10);
                                                break;
                                            default:
                                                break;
                                        }
                                        badTank.setAward(NO_POWER);
                                    }

                                }

                                // 计分榜
                                switch (badTank.getType()) {
                                    case ORDINARY_ENEMY:
                                        score.setNormalTank(score.getNormalTank() + 1);
                                        break;
                                    case FATTY_ENEMY:
                                        //肉坦克掉血不加分
                                        break;
                                    case FATTY_MINI_ENEMY:
                                        score.setFattyTank(score.getFattyTank() + 1);
                                        break;
                                    case QUICK_ENEMY:
                                        score.setFastTank(score.getFastTank() + 1);
                                        break;
                                    default:
                                        break;
                                }
                            }

                        }

                    }
                }
            }
            bulletMeet();
            ohMyGod();
            repaint();
        } while (this.gameOver == null && this.enemyTanksNumberLimit != -1);

    }

    @Override
    public void keyTyped(KeyEvent e) {

    }

    public void getDirection() {

        if (!this.playerTank.isMoving()) {
            return;
        }
        if (left && !right && !up && !down) {
            this.playerTank.setDirection(LEFT);
        } else if (!left && right && !up && !down) {
            this.playerTank.setDirection(RIGHT);
        } else if (!left && !right && up && !down) {
            this.playerTank.setDirection(UP);
        } else if (!left && !right && !up && down) {
            this.playerTank.setDirection(DOWN);
        } else if (!left && !right && !up && !down) {
            stop = true;
        }
    }

    @Override
    public void keyPressed(KeyEvent e) {
        // 对于其他的按键不处理

        if (!this.playerTank.isMoving()) {
            return;
        }
        if (e.getKeyCode() == KeyEvent.VK_W) {
            stop = false;
            this.up = true;
        } else if (e.getKeyCode() == KeyEvent.VK_A) {
            stop = false;
            this.left = true;
        } else if (e.getKeyCode() == KeyEvent.VK_S) {
            stop = false;
            this.down = true;
        } else if (e.getKeyCode() == KeyEvent.VK_D) {
            stop = false;
            this.right = true;
        }

        getDirection();

    }


    @Override
    public void keyReleased(KeyEvent e) {

        if (!this.playerTank.isMoving()) {
            return;
        }
        if (e.getKeyCode() == KeyEvent.VK_W) {
            this.up = false;
        } else if (e.getKeyCode() == KeyEvent.VK_A) {
            this.left = false;
        } else if (e.getKeyCode() == KeyEvent.VK_S) {
            this.down = false;
        } else if (e.getKeyCode() == KeyEvent.VK_D) {
            this.right = false;
        }
        if (e.getKeyCode() == KeyEvent.VK_SPACE) {
            this.playerTank.fire();
        }
        getDirection();
    }

    public GameOver getGameOver() {
        return gameOver;
    }

    public void setGameOver(GameOver gameOver) {
        this.gameOver = gameOver;
    }

    public Player getPlayerTank() {
        return playerTank;
    }

    public int getEnemyTanksNumberLimit() {
        return enemyTanksNumberLimit;
    }

    public void setEnemyTanksNumberLimit(int enemyTanksNumberLimit) {
        this.enemyTanksNumberLimit = enemyTanksNumberLimit;
    }

    public Score getScore() {
        return score;
    }

    public void setEnemyTanksAward(int enemyTanksAward) {
        this.enemyTanksAward = enemyTanksAward;
    }

    public void setEnemyTanksNumber(int enemyTanksNumber) {
        this.enemyTanksNumber = enemyTanksNumber;
    }

    public void setEnemyTanksFatty(int enemyTanksFatty) {
        this.enemyTanksFatty = enemyTanksFatty;
    }


}
